#include"snake.h"

//宏定义
#define HEIGHT 20//高度
#define WIDTH 65//宽度 
int score = 0;// 当前得分
int highScore = 0;// 最高分
int sleepTime = 320;// 移动间隔时间（毫秒）
int finalx = 0, finaly = 0;//蛇尾坐标
char dir = 'd';//初始化运动方向为右
int dx = 1, dy = 0;//右向对应的单位方向向量
int bitScore = 2;//吃到食物的加分

// 食物坐标
struct Food
{
    int x;
    int y;
} food;

//定义蛇身体的每一小节
struct BODY
{
    int x;
    int y;
};

//定义整条蛇
struct SNAKE
{
    struct BODY body[HEIGHT * WIDTH];
    int length;
}snake;

// 设置控制台颜色
void setColor(int color)
{
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
}

// 隐藏控制台光标
void hideCursor()
{
    CONSOLE_CURSOR_INFO cci;
    cci.dwSize = sizeof(cci);
    cci.bVisible = false;
    SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cci);
}

// 绘制字符画（SNAKE）
void printsnake()
{
    setColor(YELLOW);
    cout << "\n\n";
    cout << "        ███████╗███╗   ██╗ █████╗ ██╗  ██╗███████╗\n";
    cout << "        ██╔════╝████╗  ██║██╔══██╗██║ ██╔╝██╔════╝\n";
    cout << "        ███████╗██╔██╗ ██║███████║█████╔╝ █████╗  \n";
    cout << "        ╚════██║██║╚██╗██║██╔══██║██╔═██╗ ██╔══╝  \n";
    cout << "        ███████║██║ ╚████║██║  ██║██║  ██╗███████╗\n";
    cout << "        ╚══════╝╚═╝  ╚═══╝╚═╝  ╚═╝╚═╝  ╚═╝╚══════╝\n";
    setColor(WHITE);
}

// 欢迎界面
void welcomeGame()
{
    system("cls");
    printsnake();
    cout << "\n\n\t\t\t1. 开始游戏\n";
    cout << "\t\t\t2. 查看最高分\n";
    cout << "\t\t\t3. 游戏说明\n";
    cout << "\t\t\t4. 退出游戏\n";
    cout << "\n\t\t\t请选择：";
}

// 读取最高分
int readHighScore()
{
    FILE* file = fopen("save.txt", "r");
    if (file)
    {
        int res = fscanf(file, "%d", &highScore);
        if (res != 1)
        {
            highScore = 0;
        }
        fclose(file);
    }
    else highScore = 0;
    return highScore;
}

// 保存最高分
void saveHighScore()
{
    FILE* file = fopen("save.txt", "w");
    if (file)
    {
        fprintf(file, "%d", score);
        fclose(file);
    }
}

// 创建游戏地图
void createMap()
{
    setColor(WHITE);
    system("cls");
    // 绘制上边界
    for (int i = 0; i <= WIDTH; i++)cout << "_";
    cout << endl;
    // 绘制中间部分
    for (int i = 0; i < HEIGHT; i++)
    {
        cout << "|";
        for (int j = 0; j < WIDTH; j++)
        {
            if (j == WIDTH - 1)
                cout << "|";
            else
                cout << " ";
        }
        cout << endl;
    }
    // 绘制下边界
    for (int i = 0; i <= WIDTH; i++)
        cout << "_";
    cout << endl;
}

// 初始化蛇
void initSnake()
{
    snake.body[0].x = WIDTH / 2;
    snake.body[0].y = HEIGHT / 2;
    snake.body[1].x = WIDTH / 2 - 1;
    snake.body[1].y = HEIGHT / 2;
    snake.length = 2;
}

// 创建食物
void createFood()
{
    bool overlap = true;//是否重叠
    while (overlap)
    {
        overlap = false;
        //确保在地图内
        //food的x和y坐标应分别落在[1,WIDTH-1],[1,HEIGHT]内
        food.x = rand() % (WIDTH - 1) + 1;//[a,b]随机数
        food.y = rand() % HEIGHT + 1;       //rand()%(b-a+1)+a
        // 检查是否与蛇身重合
        for (int i = 0; i < snake.length; i++)
        {
            if (snake.body[i].x == food.x && snake.body[i].y == food.y)
            {
                overlap = true;
                break;
            }
        }
    }
}

// 绘制得分和提示
void drawScore()
{
    setColor(WHITE);
    COORD coord;
    coord.X = 0;
    coord.Y = HEIGHT + 3;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
    cout << "\n\t\t得分：" << score << "\t\t最高分：" << highScore;
    cout << "\n\t\t操作提示：WASD控制方向  F1加速  F2减速  ESC退出";
}

// 绘制蛇和食物
void drawGameElements()
{
    // 绘制蛇
    setColor(YELLOW);
    COORD coord;
    for (int i = 0; i < snake.length; i++)
    {
        coord.X = snake.body[i].x;
        coord.Y = snake.body[i].y;
        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
        if (i == 0)cout << "@";
        else cout << "*";
    }


    // 绘制食物
    setColor(RED);
    coord.X = food.x;
    coord.Y = food.y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
    cout << "#";
    //去除蛇尾
    coord.X = finalx;
    coord.Y = finaly;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
    cout << " ";

}

// 判断是否撞到墙
bool checkWallCollision()
{
    int a = 0, b = 0;//默认未撞到
    if (snake.body[0].x == 0 || snake.body[0].y == 0)a = 1;
    if (snake.body[0].x == WIDTH || snake.body[0].y == HEIGHT + 1)b = 1;
    return a || b;//顶部边界是额外附加的，所以判断底部墙壁时加一
}

// 判断是否咬到自己
bool checkSelfCollision()
{
    int c = 0;//默认没咬到
    for (int i = 1; i < snake.length; i++)
    {
        if (snake.body[i].x == snake.body[0].x && snake.body[i].y == snake.body[0].y)
        {
            c = 1;
            break;
        }
    }
    return c;
}

// 加速处理
void speedUp(int type)
{
    if (sleepTime > 10)
    {
        sleepTime -= 10;
        if (sleepTime <= 320 && bitScore != 2)bitScore = 2;
    }
    if (type == 1)score += 2;//按F1固定增加2
    else if (type == 2)score += bitScore;//吃到食物增加的分数
}

// 减速处理
void speedDown()
{
    if (sleepTime < 500)
    {
        sleepTime += 30;
        if (sleepTime >= 350 && bitScore != 1)bitScore = 1;
        score -= 2;//仅F2一种情况
        if (score < 0)score = 0;//保证得分非负
    }
}

// 蛇移动逻辑
void snakeMove()
{
    //记录蛇尾坐标
    finalx = snake.body[snake.length - 1].x;
    finaly = snake.body[snake.length - 1].y;
    // 移动蛇身
    for (int i = snake.length - 1; i > 0; i--)
    {
        snake.body[i].x = snake.body[i - 1].x;
        snake.body[i].y = snake.body[i - 1].y;
    }
    // 移动蛇头
    snake.body[0].x += dx;
    snake.body[0].y += dy;

    // 检查是否吃到食物
    if (snake.body[0].x == food.x && snake.body[0].y == food.y)
    {
        snake.length++; // 增加蛇身
        createFood();// 生成新食物
        speedUp(2);
    }
}

//键盘控制
void keyboardControl()
{
    if(_kbhit())//不阻塞用户输入
    {
        int key = _getch();//不显示用户输入
        if (key == 0x00 || key == 0xE0)
        {
            int exKey = _getch();
            if (exKey == 0x3B)speedUp(1);//F1
            else if (exKey == 0x3C)speedDown();//F2
        }
        else
        {
            switch (key)
            {
            case 'a':
                if (dir != 'd')
                {
                    dir = 'a';
                    dx = -1, dy = 0;
                }
                break;
            case 'd':
                if (dir != 'a')
                {
                    dir = 'd';
                    dx = 1, dy = 0;
                }
                break;
            case 'w':
                if (dir != 's')
                {
                    dir = 'w';
                    dx = 0, dy = -1;
                }
                break;
            case 's':
                if (dir != 'w')
                {
                    dir = 's';
                    dx = 0, dy = 1;
                }
                break;
            case 27:     // ESC
                exit(0);
            }
        }
    }
}

//部分清屏
void partClear()
{
    COORD coord;
    coord.X = 24;
    coord.Y = HEIGHT + 4;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
    for (int i = 0; i < 5; i++)
    {
        cout << " ";
    }
}

//打印游戏结算画面
void printFinalUI()
{
    cout << "\n\n\t\t游戏结束！得分：" << score << endl;
    if (score > highScore)
    {
        cout << "\t\t创纪录啦！最高分被你刷新啦，真棒！！！" << endl;
   